﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BacteriaSimulation.Simulation
{
    public class TaskChain
    {
        protected List<ITask> taskList;
        protected List<ITask> TaskList
        {
            get
            {
                return taskList;
            }
            set
            {
                taskList = value;
            }
        }

        protected Simulation simulation;
        public Simulation Simulation
        {
            get
            {
                return simulation;
            }
        }

        protected SimulationEnvironment environment;
        public SimulationEnvironment Environment
        {
            get
            {
                return environment;
            }
        }

        public TaskChain(Simulation simulation, SimulationEnvironment environment)
        {
            this.taskList = new List<ITask>();
            this.simulation = simulation;
            this.environment = environment;
        }

        public void AddTask(ITask task)
        {
            ITask currentLast = null;
            if (taskList.Count > 0)
            {
                currentLast = taskList.Last();
            }
            if (currentLast != null)
            {
                currentLast.SetSuccessor(task);
            }
            TaskList.Add(task);
        }

        public void execute(Bacterium bacterium)
        {
            if(taskList == null
                || taskList.Count == 0)
            {
                throw new InvalidOperationException("Task Chain not set");
            }
            ITask nextTask = taskList[0];
            while (nextTask != null)
            {
                TaskOutcome outcome = nextTask.executeTask(Simulation, bacterium, Environment);
                if (outcome.OutcomeType == TaskOutcomeType.END_CHAIN)
                {
                    return;
                }
                nextTask = nextTask.GetSuccessor();
            }
        }

        public static TaskChain BuildDefaultChain(Simulation simulation, SimulationEnvironment env)
        {
            TaskChain chain = new TaskChain(simulation, env);

            chain.AddTask(new CheckDeadBacteriumTask());
            chain.AddTask(new DuplicateBacteriumTask());
            chain.AddTask(new UpdateBacteriumPositionTask());
            chain.AddTask(new ApplyForceFieldTask());
            chain.AddTask(new DetectWallCollisionTask());
            chain.AddTask(new DetectBacteriaCollisionTask());

            return chain;
        }
    }
}
